<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
  <title>Description of imdisp</title>
  <meta name="keywords" content="imdisp">
  <meta name="description" content="IMDISP  Display one or more images nicely">
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta name="generator" content="m2html &copy; 2005 Guillaume Flandin">
  <meta name="robots" content="index, follow">
  <link type="text/css" rel="stylesheet" href="../../m2html.css">
  <script type="text/javascript">
    if (top.frames.length == 0) { top.location = "../../index.html"; };
  </script>
</head>
<body>
<a name="_top"></a>
<!-- ../menu.html VMT_4.0_dev --><!-- menu.html utils -->
<h1>imdisp
</h1>

<h2><a name="_name"></a>PURPOSE <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
<div class="box"><strong>IMDISP  Display one or more images nicely</strong></div>

<h2><a name="_synopsis"></a>SYNOPSIS <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
<div class="box"><strong>function hIm = imdisp(I, varargin) </strong></div>

<h2><a name="_description"></a>DESCRIPTION <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
<div class="fragment"><pre class="comment">IMDISP  Display one or more images nicely

 Examples:
   imdisp
   imdisp(I)
   imdisp(I, map)
   imdisp(I, lims)
   imdisp(I, map, lims)
   imdisp(..., param1, value1, param2, value2, ...)
   h = imdisp(...)

 This function displays one or more images nicely. Images can be defined
 by arrays or filenames. Multiple images can be input in a cell array or
 stacked along the fourth dimension, and are displayed as a grid of
 subplots (an improvement over MONTAGE). The size of grid is calculated or
 user defined. The figure size is set so that images are magnified by an
 integer value.

 If the image grid size is user defined, images not fitting in the grid
 can be scrolled through using the following key presses:
    Up - Back a row.
    Down - Forward a row.
    Left - Back a page (or column if there is only one row).
    Right - Forward a page (or column if there is only one row).
    Shift - 2 x speed.
    Ctrl - 4 x speed.
    Shift + Ctrl - 8 x speed.

 This allows fast scrolling through a movie or image stack, e.g. 
    imdisp(imstack, 'Size', 1)
 The function can be used as a visual DIR, e.g. 
    imdisp()
 to display all images in the current directory on a grid, or 
    imdisp({}, 'Size', 1)
 to scroll through them one at a time.

 IN:
   I - MxNxCxP array of images, or 1xP cell array. C is 1 for indexed
       images or 3 for RGB images. P is the number of images. If I is a
       cell array then each cell must contain an image. Images can equally
       be defined by filenames. If I is an empty cell array then all the
       images in the current directory are used. Default: {}.
   map - Kx3 colormap to be used with indexed images. Default: gray(256).
   lims - [LOW HIGH] display range for indexed images. Default: [min(I(:))
          max(I(:))].
   Optional parameters - name, value parameter pairs for the following:
      'Size' - [H W] size of grid to display image on. If only H is given
               then W = H. If either H or W is NaN then the number of rows
               or columns is chosen such that all images fit. If both H
               and W are NaN or the array is empty then the size of grid
               is chosen to fit all images in as large as possible.
               Default: [].
      'Indices' - 1xL list of indices of images to display. Default: 1:P.
      'Border' - [TB LR] borders to give each image top and bottom (TB)
                 and left and right (LR), to space out images. Borders are
                 normalized to the subplot size, i.e. TB = 0.01 gives a
                 border 1% of the height of each subplot. If only TB is
                 given, LR = TB. Default: 0.01.
      'DisplayRange' - Same as lims input.
      'Map' - Kx3 colormap or (additionally from above) name of MATLAB
              colormap, for use with indexed images. Default: gray(256).

 OUT:
   h - HxW array of handles to images.

   See also IMAGE, IMAGESC, IMSHOW, MONTAGE.</pre></div>

<!-- crossreference -->
<h2><a name="_cross"></a>CROSS-REFERENCE INFORMATION <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
This function calls:
<ul style="list-style-image:url(../../matlabicon.gif)">
</ul>
This function is called by:
<ul style="list-style-image:url(../../matlabicon.gif)">
</ul>
<!-- crossreference -->

<h2><a name="_subfunctions"></a>SUBFUNCTIONS <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
<ul style="list-style-image:url(../../matlabicon.gif)">
<li><a href="#_sub1" class="code">function keypress_callback(fig, event_data)</a></li><li><a href="#_sub2" class="code">function hIm = display_image(A, hAx, lims)</a></li><li><a href="#_sub3" class="code">function layout = choose_layout(n, y, x, layout)</a></li><li><a href="#_sub4" class="code">function A = imread_rgb(name)</a></li><li><a href="#_sub5" class="code">function A = imread_rgb_multi(name)</a></li><li><a href="#_sub6" class="code">function L = get_im_names</a></li><li><a href="#_sub7" class="code">function [map layout gap indices lims] = parse_inputs(inputs)</a></li><li><a href="#_sub8" class="code">function lims = default_limits(A)</a></li><li><a href="#_sub9" class="code">function lims = min_max(A)</a></li></ul>

<h2><a name="_source"></a>SOURCE CODE <a href="#_top"><img alt="^" border="0" src="../../up.png"></a></h2>
<div class="fragment"><pre>0001 <a name="_sub0" href="#_subfunctions" class="code">function hIm = imdisp(I, varargin)</a>
0002 <span class="comment">%IMDISP  Display one or more images nicely</span>
0003 <span class="comment">%</span>
0004 <span class="comment">% Examples:</span>
0005 <span class="comment">%   imdisp</span>
0006 <span class="comment">%   imdisp(I)</span>
0007 <span class="comment">%   imdisp(I, map)</span>
0008 <span class="comment">%   imdisp(I, lims)</span>
0009 <span class="comment">%   imdisp(I, map, lims)</span>
0010 <span class="comment">%   imdisp(..., param1, value1, param2, value2, ...)</span>
0011 <span class="comment">%   h = imdisp(...)</span>
0012 <span class="comment">%</span>
0013 <span class="comment">% This function displays one or more images nicely. Images can be defined</span>
0014 <span class="comment">% by arrays or filenames. Multiple images can be input in a cell array or</span>
0015 <span class="comment">% stacked along the fourth dimension, and are displayed as a grid of</span>
0016 <span class="comment">% subplots (an improvement over MONTAGE). The size of grid is calculated or</span>
0017 <span class="comment">% user defined. The figure size is set so that images are magnified by an</span>
0018 <span class="comment">% integer value.</span>
0019 <span class="comment">%</span>
0020 <span class="comment">% If the image grid size is user defined, images not fitting in the grid</span>
0021 <span class="comment">% can be scrolled through using the following key presses:</span>
0022 <span class="comment">%    Up - Back a row.</span>
0023 <span class="comment">%    Down - Forward a row.</span>
0024 <span class="comment">%    Left - Back a page (or column if there is only one row).</span>
0025 <span class="comment">%    Right - Forward a page (or column if there is only one row).</span>
0026 <span class="comment">%    Shift - 2 x speed.</span>
0027 <span class="comment">%    Ctrl - 4 x speed.</span>
0028 <span class="comment">%    Shift + Ctrl - 8 x speed.</span>
0029 <span class="comment">%</span>
0030 <span class="comment">% This allows fast scrolling through a movie or image stack, e.g.</span>
0031 <span class="comment">%    imdisp(imstack, 'Size', 1)</span>
0032 <span class="comment">% The function can be used as a visual DIR, e.g.</span>
0033 <span class="comment">%    imdisp()</span>
0034 <span class="comment">% to display all images in the current directory on a grid, or</span>
0035 <span class="comment">%    imdisp({}, 'Size', 1)</span>
0036 <span class="comment">% to scroll through them one at a time.</span>
0037 <span class="comment">%</span>
0038 <span class="comment">% IN:</span>
0039 <span class="comment">%   I - MxNxCxP array of images, or 1xP cell array. C is 1 for indexed</span>
0040 <span class="comment">%       images or 3 for RGB images. P is the number of images. If I is a</span>
0041 <span class="comment">%       cell array then each cell must contain an image. Images can equally</span>
0042 <span class="comment">%       be defined by filenames. If I is an empty cell array then all the</span>
0043 <span class="comment">%       images in the current directory are used. Default: {}.</span>
0044 <span class="comment">%   map - Kx3 colormap to be used with indexed images. Default: gray(256).</span>
0045 <span class="comment">%   lims - [LOW HIGH] display range for indexed images. Default: [min(I(:))</span>
0046 <span class="comment">%          max(I(:))].</span>
0047 <span class="comment">%   Optional parameters - name, value parameter pairs for the following:</span>
0048 <span class="comment">%      'Size' - [H W] size of grid to display image on. If only H is given</span>
0049 <span class="comment">%               then W = H. If either H or W is NaN then the number of rows</span>
0050 <span class="comment">%               or columns is chosen such that all images fit. If both H</span>
0051 <span class="comment">%               and W are NaN or the array is empty then the size of grid</span>
0052 <span class="comment">%               is chosen to fit all images in as large as possible.</span>
0053 <span class="comment">%               Default: [].</span>
0054 <span class="comment">%      'Indices' - 1xL list of indices of images to display. Default: 1:P.</span>
0055 <span class="comment">%      'Border' - [TB LR] borders to give each image top and bottom (TB)</span>
0056 <span class="comment">%                 and left and right (LR), to space out images. Borders are</span>
0057 <span class="comment">%                 normalized to the subplot size, i.e. TB = 0.01 gives a</span>
0058 <span class="comment">%                 border 1% of the height of each subplot. If only TB is</span>
0059 <span class="comment">%                 given, LR = TB. Default: 0.01.</span>
0060 <span class="comment">%      'DisplayRange' - Same as lims input.</span>
0061 <span class="comment">%      'Map' - Kx3 colormap or (additionally from above) name of MATLAB</span>
0062 <span class="comment">%              colormap, for use with indexed images. Default: gray(256).</span>
0063 <span class="comment">%</span>
0064 <span class="comment">% OUT:</span>
0065 <span class="comment">%   h - HxW array of handles to images.</span>
0066 <span class="comment">%</span>
0067 <span class="comment">%   See also IMAGE, IMAGESC, IMSHOW, MONTAGE.</span>
0068 
0069 <span class="comment">% Parse inputs</span>
0070 [map layout gap indices lims] = <a href="#_sub7" class="code" title="subfunction [map layout gap indices lims] = parse_inputs(inputs)">parse_inputs</a>(varargin);
0071 
0072 <span class="keyword">if</span> nargin == 0 || (iscell(I) &amp;&amp; isempty(I))
0073     <span class="comment">% Read in all the images in the directory</span>
0074     I = <a href="#_sub6" class="code" title="subfunction L = get_im_names">get_im_names</a>;
0075     <span class="keyword">if</span> isempty(I)
0076         <span class="comment">% No images found</span>
0077         <span class="keyword">if</span> nargout &gt; 0
0078             hIm = [];
0079         <span class="keyword">end</span>
0080         <span class="keyword">return</span>
0081     <span class="keyword">end</span>
0082 <span class="keyword">end</span>
0083 
0084 <span class="comment">% Check if input is filenames</span>
0085 <span class="keyword">if</span> ischar(I)
0086     [x y c] = size(I);
0087     <span class="keyword">if</span> (x &gt; 1 &amp;&amp; y &gt; 1) || c &gt; 1 
0088         I = num2cell(I, 2);
0089     <span class="keyword">else</span>
0090         I = {I(:)'};
0091     <span class="keyword">end</span>
0092 <span class="keyword">end</span>
0093 
0094 <span class="comment">% Get limits, etc.</span>
0095 <span class="keyword">if</span> isnumeric(I) || islogical(I)
0096     [y x c n] = size(I);
0097     <span class="keyword">if</span> isempty(lims)
0098         lims = <a href="#_sub9" class="code" title="subfunction lims = min_max(A)">min_max</a>(I);
0099     <span class="keyword">elseif</span> isequal(0, lims)
0100         lims = <a href="#_sub8" class="code" title="subfunction lims = default_limits(A)">default_limits</a>(I);
0101     <span class="keyword">elseif</span> c == 3
0102         <span class="comment">% Rescale</span>
0103         <span class="keyword">if</span> ~isfloat(I)
0104             I = single(I);
0105         <span class="keyword">end</span>
0106         I = min(max((I - lims(1)) ./ (lims(2) - lims(1)), 0), 1);
0107     <span class="keyword">end</span>
0108     <span class="keyword">if</span> isfloat(I) &amp;&amp; c == 3 &amp;&amp; n &gt; 1
0109         I = uint8(I * 256 - 0.5);
0110         lims = round(lims * 256 - 0.5);
0111     <span class="keyword">end</span>
0112 <span class="keyword">elseif</span> iscell(I)
0113     n = numel(I);
0114     A = I{1};
0115     <span class="keyword">if</span> ischar(A)
0116         <span class="comment">% Read in the image (or images for multi-frame files)</span>
0117         <span class="keyword">if</span> n == 1
0118             I = <a href="#_sub5" class="code" title="subfunction A = imread_rgb_multi(name)">imread_rgb_multi</a>(A);
0119             <span class="keyword">if</span> iscell(I)
0120                 n = numel(I);
0121                 A = I{1};
0122                 [y x c] = size(A);
0123             <span class="keyword">else</span>
0124                 [y x c n] = size(I);
0125                 A = I;
0126             <span class="keyword">end</span>
0127         <span class="keyword">else</span>
0128             A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(A);
0129             I{1} = A;
0130             [y x c] = size(A);
0131         <span class="keyword">end</span>
0132     <span class="keyword">else</span>
0133         [y x c] = size(A);
0134     <span class="keyword">end</span>
0135     <span class="comment">% Assume all images are the same size and type as the first</span>
0136     <span class="keyword">if</span> isempty(lims) || isequal(0, lims)
0137         lims = <a href="#_sub8" class="code" title="subfunction lims = default_limits(A)">default_limits</a>(A);
0138     <span class="keyword">end</span>
0139 <span class="keyword">else</span>
0140     error(<span class="string">'I not of recognized type.'</span>);
0141 <span class="keyword">end</span>
0142 
0143 <span class="comment">% Select indexed images</span>
0144 <span class="keyword">if</span> ~isequal(indices, -1)
0145     <span class="keyword">if</span> iscell(I)
0146         I = I(indices);
0147         n = numel(I);
0148     <span class="keyword">else</span>
0149         I = I(:,:,:,indices);
0150         n = size(I, 4);
0151     <span class="keyword">end</span>
0152 <span class="keyword">end</span>
0153 
0154 <span class="comment">% Get the current figure</span>
0155 hFig = get(0, <span class="string">'CurrentFigure'</span>);
0156 <span class="keyword">if</span> isempty(hFig)
0157     <span class="comment">% Create a new figure</span>
0158     hFig = figure;
0159 <span class="keyword">elseif</span> n &gt; 1
0160     <span class="comment">% Clear the figure</span>
0161     hFig = clf(hFig, <span class="string">'reset'</span>);
0162 <span class="keyword">end</span>
0163 
0164 <span class="comment">% Set the colormap</span>
0165 set(hFig, <span class="string">'Colormap'</span>, map);
0166 
0167 <span class="comment">% Display the image(s)</span>
0168 <span class="keyword">if</span> n == 0
0169     hIm = <a href="#_sub2" class="code" title="subfunction hIm = display_image(A, hAx, lims)">display_image</a>([], gca, [0 1]);
0170     
0171     <span class="keyword">if</span> nargout == 0
0172         clear hIm <span class="comment">% Avoid printing this out</span>
0173     <span class="keyword">end</span>
0174     <span class="keyword">return</span>
0175 <span class="keyword">elseif</span> n == 1
0176     <span class="comment">% IMSHOW mode</span>
0177     <span class="comment">% Display the single image</span>
0178     hAx = gca;
0179     <span class="keyword">if</span> iscell(I)
0180         I = I{1};
0181     <span class="keyword">end</span>
0182     hIm = <a href="#_sub2" class="code" title="subfunction hIm = display_image(A, hAx, lims)">display_image</a>(I, hAx, lims);
0183     
0184     <span class="keyword">if</span> nargout == 0
0185         clear hIm <span class="comment">% Avoid printing this out</span>
0186     <span class="keyword">end</span>
0187     
0188     <span class="comment">% Only resize image if it is alone in the figure</span>
0189     <span class="keyword">if</span> numel(findobj(get(hFig, <span class="string">'Children'</span>), <span class="string">'Type'</span>, <span class="string">'axes'</span>)) &gt; 1
0190         <span class="keyword">return</span>
0191     <span class="keyword">end</span>
0192     <span class="comment">% Could still be the first subplot - do another check</span>
0193     axesPos = get(hAx, <span class="string">'Position'</span>);
0194     newAxesPos = [gap(1) gap(end) 1-2*gap(1) 1-2*gap(end)];
0195     <span class="keyword">if</span> isequal(axesPos, get(hFig, <span class="string">'DefaultAxesPosition'</span>))
0196         <span class="comment">% Default position =&gt; not a subplot</span>
0197         <span class="comment">% Fill the window</span>
0198         set(hAx, <span class="string">'Units'</span>, <span class="string">'normalized'</span>, <span class="string">'Position'</span>, newAxesPos);
0199         axesPos = newAxesPos;
0200     <span class="keyword">end</span>
0201     <span class="keyword">if</span> ~isequal(axesPos, newAxesPos)
0202         <span class="comment">% Figure not alone, so don't resize.</span>
0203         <span class="keyword">return</span>
0204     <span class="keyword">end</span>
0205     layout = [1 1];
0206 <span class="keyword">else</span>
0207     <span class="comment">% MONTAGE mode</span>
0208     <span class="comment">% Compute a good layout</span>
0209     layout = <a href="#_sub3" class="code" title="subfunction layout = choose_layout(n, y, x, layout)">choose_layout</a>(n, y, x, layout);
0210 
0211     <span class="comment">% Create a data structure to store the data in</span>
0212     num = prod(layout);
0213     state.num = num * ceil(n / num);
0214     hIm = zeros(layout);
0215     hAx = zeros(layout);
0216 
0217     <span class="comment">% Set the first lot of images</span>
0218     index = mod(0:num-1, state.num) + 1;
0219     hw = 1 ./ layout;
0220     gap = gap ./ layout;
0221     dims = hw - 2 * gap;
0222     dims = dims([2 1]);
0223     <span class="keyword">for</span> a = 1:layout(1)
0224         <span class="keyword">for</span> b = 1:layout(2)
0225             c = index(b + (layout(1) - a) * layout(2));
0226             <span class="keyword">if</span> c &gt; n
0227                 A = [];
0228             <span class="keyword">elseif</span> iscell(I)
0229                 A = I{c};
0230                 <span class="keyword">if</span> ischar(A)
0231                     A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(A);
0232                     I{c} = A;
0233                 <span class="keyword">end</span>
0234             <span class="keyword">else</span>
0235                 A = I(:,:,:,c);
0236             <span class="keyword">end</span>
0237             hAx(a,b) = axes(<span class="string">'Position'</span>, [(b-1)*hw(2)+gap(2) (a-1)*hw(1)+gap(1) dims], <span class="string">'Units'</span>, <span class="string">'normalized'</span>);
0238             hIm(a,b) = <a href="#_sub2" class="code" title="subfunction hIm = display_image(A, hAx, lims)">display_image</a>(A, hAx(a,b), lims);
0239         <span class="keyword">end</span>
0240     <span class="keyword">end</span>
0241     
0242     <span class="comment">% Check if we need to be able to scroll through images</span>
0243     <span class="keyword">if</span> n &gt; num
0244         <span class="comment">% Intialize rest of data structure</span>
0245         state.hIm = hIm;
0246         state.hAx = hAx;
0247         state.index = 1;
0248         state.layout = layout;
0249         state.n = n;
0250         state.I = I;
0251         <span class="comment">% Set the callback for image navigation, and save the image data in the figure</span>
0252         set(hFig, <span class="string">'KeyPressFcn'</span>, @<a href="#_sub1" class="code" title="subfunction keypress_callback(fig, event_data)">keypress_callback</a>, <span class="string">'Interruptible'</span>, <span class="string">'off'</span>, <span class="string">'BusyAction'</span>, <span class="string">'cancel'</span>, <span class="string">'UserData'</span>, state);
0253     <span class="keyword">end</span>
0254     
0255     <span class="comment">% Flip hIm so it matches the layout</span>
0256     hIm = hIm(end:-1:1,:);
0257     
0258     <span class="keyword">if</span> nargout == 0
0259         clear hIm <span class="comment">% Avoid printing this out</span>
0260     <span class="keyword">end</span>
0261 <span class="keyword">end</span>
0262 
0263 <span class="keyword">if</span> strcmp(get(hFig, <span class="string">'WindowStyle'</span>), <span class="string">'docked'</span>)
0264     <span class="comment">% Figure is docked, so can't resize</span>
0265     <span class="keyword">return</span>
0266 <span class="keyword">end</span>
0267 
0268 <span class="comment">% Set the figure size well</span>
0269 <span class="comment">% Compute the image size</span>
0270 ImSz = layout([2 1]) .* [x y] ./ (1 - 2 * gap([end 1]));
0271     
0272 <span class="comment">% Get the size of the monitor we're on</span>
0273 figPosCur = get(hFig, <span class="string">'Position'</span>);
0274 <span class="comment">% Monitor sizes</span>
0275 MonSz = get(0, <span class="string">'MonitorPositions'</span>);
0276 MonOn = size(MonSz, 1);
0277 <span class="keyword">if</span> MonOn &gt; 1
0278     <span class="comment">% Make the origin the top left corner of the primary monitor</span>
0279     correction = 0;
0280     <span class="keyword">if</span> ispc
0281         <span class="keyword">for</span> a = 1:MonOn
0282             <span class="keyword">if</span> isequal(MonSz(a,1:2), [1 1])
0283                 correction = MonSz(a,4);
0284                 <span class="keyword">break</span>
0285             <span class="keyword">end</span>
0286         <span class="keyword">end</span>
0287     <span class="keyword">end</span>
0288     <span class="comment">% Determine which monitor the centre of the image is on</span>
0289     figCenter = figPosCur(1:2) + figPosCur(3:4) / 2;
0290     figCenter = MonSz - repmat(figCenter, [MonOn 2]);
0291     MonOn = all(sign(figCenter) == repmat([-1 -1 1 1], [MonOn 1]), 2);
0292     MonOn(1) = MonOn(1) | ~any(MonOn);
0293     MonSz = MonSz(MonOn,:);
0294     <span class="comment">% Correct the size</span>
0295     MonSz(3:4) = MonSz(3:4) - MonSz(1:2) + 1;
0296     <span class="comment">% Correct the origin</span>
0297     <span class="keyword">if</span> correction
0298         MonSz(2) = correction - MonSz(4) - MonSz(2) + 2;
0299     <span class="keyword">end</span>
0300 <span class="keyword">end</span>
0301 
0302 <span class="comment">% Check if the window is maximized</span>
0303 <span class="comment">% This is a hack which may only work on Windows! No matter, though.</span>
0304 <span class="keyword">if</span> isequal(MonSz([1 3]), figPosCur([1 3]))
0305     <span class="comment">% Leave maximized</span>
0306     <span class="keyword">return</span>
0307 <span class="keyword">end</span>
0308 
0309 <span class="comment">% Compute the size to set the window</span>
0310 MaxSz = MonSz(3:4) - [20 120];
0311 RescaleFactor = min(MaxSz ./ ImSz);
0312 <span class="keyword">if</span> RescaleFactor &gt; 1
0313     <span class="comment">% Integer scale for enlarging, but don't make too big</span>
0314     MaxSz = min(MaxSz, [1200 800]);
0315     RescaleFactor = max(floor(min(MaxSz ./ ImSz)), 1);
0316 <span class="keyword">end</span>
0317 figPosNew = ceil(ImSz * RescaleFactor);
0318 
0319 <span class="comment">% Don't move the figure if the size isn't changing</span>
0320 <span class="keyword">if</span> isequal(figPosCur(3:4), figPosNew)
0321     <span class="keyword">return</span>
0322 <span class="keyword">end</span>
0323 
0324 <span class="comment">% Keep the centre of the figure stationary</span>
0325 figPosNew = [floor(figPosCur(1:2)+(figPosCur(3:4)-figPosNew)/2) figPosNew];
0326 
0327 <span class="comment">% Ensure the figure is in bounds</span>
0328 figPosNew(1:2) = min(max(figPosNew(1:2), MonSz(1:2)+6), MonSz(1:2)+MonSz(3:4)-[6 101]-figPosNew(3:4));
0329 
0330 <span class="comment">% Set the figure size and position</span>
0331 set(hFig, <span class="string">'Position'</span>, figPosNew);
0332 <span class="keyword">return</span>
0333 
0334 <span class="comment">%% Keypress callback</span>
0335 <span class="comment">% The function which does all the display stuff</span>
0336 <a name="_sub1" href="#_subfunctions" class="code">function keypress_callback(fig, event_data)</a>
0337 <span class="comment">% Check what key was pressed and update the image index as necessary</span>
0338 <span class="keyword">switch</span> event_data.Character
0339     <span class="keyword">case</span> 28 <span class="comment">% Left</span>
0340         up = -1; <span class="comment">% Back a page</span>
0341     <span class="keyword">case</span> 29 <span class="comment">% Right</span>
0342         up = 1; <span class="comment">% Forward a page</span>
0343     <span class="keyword">case</span> 30 <span class="comment">% Up</span>
0344         up = -0.1; <span class="comment">% Back a row</span>
0345     <span class="keyword">case</span> 31 <span class="comment">% Down</span>
0346         up = 0.1; <span class="comment">% Forward a row</span>
0347     <span class="keyword">otherwise</span>
0348         <span class="comment">% Another key was pressed - ignore it</span>
0349         <span class="keyword">return</span>
0350 <span class="keyword">end</span>
0351 <span class="comment">% Use control and shift for faster scrolling</span>
0352 <span class="keyword">if</span> ~isempty(event_data.Modifier)
0353     up = up * (2 ^ (strcmpi(event_data.Modifier, {<span class="string">'shift'</span>, <span class="string">'control'</span>}) * [1; 2]));
0354 <span class="keyword">end</span>
0355 <span class="comment">% Get the state data</span>
0356 state = get(fig, <span class="string">'UserData'</span>);
0357 <span class="comment">% Get the current index</span>
0358 index = state.index;
0359 <span class="comment">% Get number of images</span>
0360 n = prod(state.layout);
0361 <span class="comment">% Generate 12 valid indices</span>
0362 <span class="keyword">if</span> abs(up) &lt; 1
0363     <span class="comment">% Increment by row</span>
0364     index = index + state.layout(2) * (up * 10) - 1;
0365 <span class="keyword">else</span>
0366     <span class="keyword">if</span> state.layout(1) == 1
0367         <span class="comment">% Increment by column</span>
0368         index = index + up - 1;
0369     <span class="keyword">else</span>
0370         <span class="comment">% Increment by page</span>
0371         index = index + n * up - 1;
0372     <span class="keyword">end</span>
0373 <span class="keyword">end</span>
0374 index = mod(index:index+n, state.num) + 1;
0375 <span class="comment">% Plot the images</span>
0376 figure(fig);
0377 <span class="keyword">for</span> a = 1:state.layout(1)
0378     <span class="keyword">for</span> b = 1:state.layout(2)
0379         <span class="comment">% Get the image</span>
0380         c = index(b + (state.layout(1) - a) * state.layout(2));
0381         <span class="keyword">if</span> c &gt; state.n
0382             <span class="comment">% Set the image data</span>
0383             set(state.hIm(a,b), <span class="string">'CData'</span>, []);
0384         <span class="keyword">elseif</span> iscell(state.I)
0385             A = state.I{c};
0386             <span class="keyword">if</span> ischar(A)
0387                 <span class="comment">% Filename - read the image from disk</span>
0388                 A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(A);
0389                 state.I{c} = A;
0390             <span class="keyword">end</span>
0391             <span class="comment">% Set the image data</span>
0392             set(state.hIm(a,b), <span class="string">'CData'</span>, A);
0393             <span class="comment">% Reset the axes limits</span>
0394             <span class="keyword">if</span> ~isempty(A)
0395                 set(state.hAx(a,b), <span class="string">'XLim'</span>, [0.5 size(A, 2)+0.5], <span class="string">'YLim'</span>, [0.5 size(A, 1)+0.5]);
0396             <span class="keyword">end</span>
0397         <span class="keyword">else</span>
0398             <span class="comment">% Set the image data</span>
0399             set(state.hIm(a,b), <span class="string">'CData'</span>, state.I(:,:,:,c));
0400         <span class="keyword">end</span>
0401     <span class="keyword">end</span>
0402 <span class="keyword">end</span>
0403 drawnow;
0404 <span class="comment">% Save the current index</span>
0405 state.index = index(1);
0406 set(fig, <span class="string">'UserData'</span>, state);
0407 <span class="keyword">return</span>
0408 
0409 <span class="comment">%% Display the image</span>
0410 <a name="_sub2" href="#_subfunctions" class="code">function hIm = display_image(A, hAx, lims)</a>
0411 <span class="keyword">if</span> isempty(A)
0412     hIm = image(zeros(1, 1, 3));
0413     set(hIm, <span class="string">'CData'</span>, []);
0414 <span class="keyword">else</span>
0415     hIm = image(A);
0416 <span class="keyword">end</span>
0417 set(hAx, <span class="string">'Visible'</span>, <span class="string">'off'</span>, <span class="string">'DataAspectRatio'</span>, [1 1 1], <span class="string">'DrawMode'</span>, <span class="string">'fast'</span>, <span class="string">'CLim'</span>, lims);
0418 set(get(hAx, <span class="string">'XLabel'</span>), <span class="string">'Visible'</span>, <span class="string">'on'</span>);
0419 set(get(hAx, <span class="string">'YLabel'</span>), <span class="string">'Visible'</span>, <span class="string">'on'</span>);
0420 set(get(hAx, <span class="string">'Title'</span>), <span class="string">'Visible'</span>, <span class="string">'on'</span>);
0421 set(hIm, <span class="string">'CDataMapping'</span>, <span class="string">'scaled'</span>);
0422 <span class="keyword">return</span>
0423 
0424 <span class="comment">%% Choose a good layout for the images</span>
0425 <a name="_sub3" href="#_subfunctions" class="code">function layout = choose_layout(n, y, x, layout)</a>
0426 v = numel(layout);
0427 N = isnan(layout);
0428 <span class="keyword">if</span> v == 0 || all(N)
0429     <span class="comment">% Compute approximate layout</span>
0430     sz = get(0, <span class="string">'ScreenSize'</span>);
0431     sz = sz(3:4) ./ [x y];
0432     layout = ceil(sz([2 1]) ./ sqrt(prod(sz) / n));
0433     <span class="comment">% Remove superfluous rows or columns</span>
0434     <span class="keyword">while</span> 1
0435         <span class="keyword">switch</span> ([prod(layout - [1 0]) prod(layout - [0 1])] &gt;= n) * [2; 1]
0436             <span class="keyword">case</span> 0
0437                 <span class="keyword">break</span>;
0438             <span class="keyword">case</span> 1
0439                 layout = layout - [0 1];
0440             <span class="keyword">case</span> 2
0441                 layout = layout - [1 0];
0442             <span class="keyword">case</span> 3
0443                 <span class="keyword">if</span> min(sz .* (layout - [0 1])) &gt; min(sz .* (layout - [1 0]))
0444                     layout = layout - [0 1];
0445                 <span class="keyword">else</span>
0446                     layout = layout - [1 0];
0447                 <span class="keyword">end</span>
0448         <span class="keyword">end</span>
0449     <span class="keyword">end</span>
0450 <span class="keyword">elseif</span> v == 1
0451     layout = layout([1 1]);
0452 <span class="keyword">elseif</span> any(N)
0453     layout(N) = ceil(n / layout(~N));
0454 <span class="keyword">end</span>
0455 layout = reshape(layout, 1, 2);
0456 <span class="keyword">return</span>
0457 
0458 <span class="comment">%% Read image to uint8 rgb array</span>
0459 <a name="_sub4" href="#_subfunctions" class="code">function A = imread_rgb(name)</a>
0460 <span class="keyword">try</span>
0461     [A map alpha] = imread(name);
0462 <span class="keyword">catch</span>
0463     <span class="comment">% Format not recognized by imread, so create a red cross (along diagonals)</span>
0464     A = eye(101) | diag(ones(100, 1), 1) | diag(ones(100, 1), -1);
0465     A = (uint8(1) - uint8(A | flipud(A))) * uint8(255);
0466     A = cat(3, zeros(size(A), <span class="string">'uint8'</span>)+uint8(255), A, A);
0467     <span class="keyword">return</span>
0468 <span class="keyword">end</span>
0469 A = A(:,:,:,1); <span class="comment">% Keep only first frame of multi-frame files</span>
0470 <span class="keyword">if</span> ~isempty(map)
0471     map = uint8(map * 256 - 0.5); <span class="comment">% Convert to uint8 for storage</span>
0472     A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); <span class="comment">% Assume indexed from 0</span>
0473 <span class="keyword">elseif</span> size(A, 3) == 4
0474     <span class="keyword">if</span> lower(name(end)) == <span class="string">'f'</span>
0475         <span class="comment">% TIFF in CMYK colourspace - convert to RGB</span>
0476         <span class="keyword">if</span> isfloat(A)
0477             A = A * 255;
0478         <span class="keyword">else</span>
0479             A = single(A);
0480         <span class="keyword">end</span>
0481         A = 255 - A;
0482         A(:,:,4) = A(:,:,4) / 255;
0483         A = uint8(A(:,:,1:3) .* A(:,:,[4 4 4]));
0484     <span class="keyword">else</span>
0485         <span class="comment">% Assume 4th channel is an alpha matte</span>
0486         alpha = A(:,:,4);
0487         A = A(:,:,1:3);
0488     <span class="keyword">end</span>
0489 <span class="keyword">end</span>
0490 <span class="keyword">if</span> ~isempty(alpha)
0491     <span class="comment">% Apply transprency over a grey checkerboard pattern</span>
0492     <span class="keyword">if</span> isa(alpha, <span class="string">'uint8'</span>)
0493         alpha = double(alpha) / 255;
0494     <span class="keyword">end</span>
0495     A = double(A) .* alpha(:,:,ones(1, size(A, 3)));
0496     sqSz = max(size(alpha));
0497     sqSz = floor(max(log(sqSz / 100), 0) * 10 + 1 + min(sqSz, 100) / 20);
0498     grid = repmat(85, ceil(size(alpha) / sqSz));
0499     grid(2:2:<span class="keyword">end</span>,1:2:end) = 171;
0500     grid(1:2:<span class="keyword">end</span>,2:2:end) = 171;
0501     grid = kron(grid, ones(sqSz));
0502     alpha = grid(1:size(A, 1),1:size(A, 2)) .* (1 - alpha);
0503     A = uint8(A + alpha(:,:,ones(1, size(A, 3))));
0504 <span class="keyword">end</span>
0505 <span class="keyword">return</span>
0506 
0507 <span class="comment">%% Read (potentially) multi-frame image to uint8 rgb array</span>
0508 <a name="_sub5" href="#_subfunctions" class="code">function A = imread_rgb_multi(name)</a>
0509 <span class="keyword">try</span>
0510     <span class="comment">% Get file info</span>
0511     info = imfinfo(name);
0512 <span class="keyword">catch</span>
0513     <span class="comment">% Revert to standard case</span>
0514     A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(name);
0515     <span class="keyword">return</span>
0516 <span class="keyword">end</span>
0517 <span class="keyword">if</span> numel(info) &lt; 2
0518     <span class="comment">% Single image</span>
0519     A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(name);
0520     <span class="keyword">return</span>
0521 <span class="keyword">else</span>
0522     <span class="comment">% Multi-frame image</span>
0523     <span class="keyword">switch</span> lower(info(1).Format)
0524         <span class="keyword">case</span> <span class="string">'gif'</span>
0525             [A map] = imread(name, <span class="string">'frames'</span>, <span class="string">'all'</span>);
0526             <span class="keyword">if</span> ~isempty(map)
0527                 map = uint8(map * 256 - 0.5); <span class="comment">% Convert to uint8 for storage</span>
0528                 A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); <span class="comment">% Assume indexed from 0</span>
0529                 A = permute(A, [1 2 5 4 3]);
0530             <span class="keyword">end</span>
0531         <span class="keyword">case</span> {<span class="string">'tif'</span>, <span class="string">'tiff'</span>}
0532             A = cell(numel(info), 1);
0533             <span class="keyword">for</span> a = 1:numel(A)
0534                 [A{a} map] = imread(name, <span class="string">'Index'</span>, a, <span class="string">'Info'</span>, info);
0535                 <span class="keyword">if</span> ~isempty(map)
0536                     map = uint8(map * 256 - 0.5); <span class="comment">% Convert to uint8 for storage</span>
0537                     A{a} = reshape(map(uint32(A{a})+1,:), [size(A) size(map, 2)]); <span class="comment">% Assume indexed from 0</span>
0538                 <span class="keyword">end</span>
0539                 <span class="keyword">if</span> size(A{a}, 3) == 4
0540                     <span class="comment">% TIFF in CMYK colourspace - convert to RGB</span>
0541                     <span class="keyword">if</span> isfloat(A{a})
0542                         A{a} = A{a} * 255;
0543                     <span class="keyword">else</span>
0544                         A{a} = single(A{a});
0545                     <span class="keyword">end</span>
0546                     A{a} = 255 - A{a};
0547                     A{a}(:,:,4) = A{a}(:,:,4) / 255;
0548                     A{a} = uint8(A(:,:,1:3) .* A{a}(:,:,[4 4 4]));
0549                 <span class="keyword">end</span>
0550             <span class="keyword">end</span>
0551         <span class="keyword">otherwise</span>
0552             <span class="comment">% Multi-frame not supported for this format</span>
0553             A = <a href="#_sub4" class="code" title="subfunction A = imread_rgb(name)">imread_rgb</a>(name);
0554             <span class="keyword">return</span>
0555     <span class="keyword">end</span>
0556 <span class="keyword">end</span>
0557 <span class="keyword">return</span>
0558 
0559 <span class="comment">%% Get the names of all images in a directory</span>
0560 <a name="_sub6" href="#_subfunctions" class="code">function L = get_im_names</a>
0561 D = dir;
0562 n = 0;
0563 L = cell(size(D));
0564 <span class="comment">% Go through the directory list</span>
0565 <span class="keyword">for</span> a = 1:numel(D)
0566     <span class="comment">% Check if file is a supported image type</span>
0567     <span class="keyword">if</span> numel(D(a).name) &gt; 4 &amp;&amp; ~D(a).isdir &amp;&amp; (any(strcmpi(D(a).name(end-3:end), {<span class="string">'.png'</span>, <span class="string">'.tif'</span>, <span class="string">'.jpg'</span>, <span class="string">'.bmp'</span>, <span class="string">'.ppm'</span>, <span class="string">'.pgm'</span>, <span class="string">'.pbm'</span>, <span class="string">'.gif'</span>, <span class="string">'.ras'</span>})) || any(strcmpi(D(a).name(end-4:end), {<span class="string">'.tiff'</span>, <span class="string">'.jpeg'</span>})))
0568         n = n + 1;
0569         L{n} = D(a).name;
0570     <span class="keyword">end</span>
0571 <span class="keyword">end</span>
0572 L = L(1:n);
0573 <span class="keyword">return</span>
0574 
0575 <span class="comment">%% Parse inputs</span>
0576 <a name="_sub7" href="#_subfunctions" class="code">function [map layout gap indices lims] = parse_inputs(inputs)</a>
0577 
0578 <span class="comment">% Set defaults</span>
0579 map = [];
0580 layout = [];
0581 gap = 0;
0582 indices = -1;
0583 lims = 0;
0584 
0585 <span class="comment">% Check for map and display range</span>
0586 <span class="keyword">for</span> b = 1:numel(inputs)
0587     <span class="keyword">if</span> ~isnumeric(inputs{b})
0588         b = b - 1;
0589         <span class="keyword">break</span>;
0590     <span class="keyword">end</span>
0591     <span class="keyword">if</span> size(inputs{b}, 2) == 3
0592         map = inputs{b};
0593     <span class="keyword">elseif</span> numel(inputs{b}) &lt; 3
0594         lims = inputs{b};
0595     <span class="keyword">end</span>
0596 <span class="keyword">end</span>
0597 
0598 <span class="comment">% Go through option pairs</span>
0599 <span class="keyword">for</span> a = b+1:2:numel(inputs)
0600     <span class="keyword">switch</span> lower(inputs{a})
0601         <span class="keyword">case</span> <span class="string">'map'</span>
0602             map = inputs{a+1};
0603             <span class="keyword">if</span> ischar(map)
0604                 map = feval(map, 256);
0605             <span class="keyword">end</span>
0606         <span class="keyword">case</span> {<span class="string">'size'</span>, <span class="string">'grid'</span>}
0607             layout = inputs{a+1};
0608         <span class="keyword">case</span> {<span class="string">'gap'</span>, <span class="string">'border'</span>}
0609             gap = inputs{a+1};
0610         <span class="keyword">case</span> <span class="string">'indices'</span>
0611             indices = inputs{a+1};
0612         <span class="keyword">case</span> {<span class="string">'lims'</span>, <span class="string">'displayrange'</span>}
0613             lims = inputs{a+1};
0614         <span class="keyword">otherwise</span>
0615             error(<span class="string">'Input option %s not recognized'</span>, inputs{a});
0616     <span class="keyword">end</span>
0617 <span class="keyword">end</span>
0618 
0619 <span class="keyword">if</span> isempty(map)
0620    map = gray(256);
0621 <span class="keyword">end</span>
0622 <span class="keyword">return</span>
0623 
0624 <span class="comment">%% Return default limits for the image type</span>
0625 <a name="_sub8" href="#_subfunctions" class="code">function lims = default_limits(A)</a>
0626 <span class="keyword">if</span> size(A, 3) == 1
0627     lims = <a href="#_sub9" class="code" title="subfunction lims = min_max(A)">min_max</a>(A);
0628 <span class="keyword">else</span>
0629     lims = [0 1];
0630     <span class="keyword">if</span> ~isfloat(A)
0631         lims = lims * double(intmax(class(A)));
0632     <span class="keyword">end</span>
0633 <span class="keyword">end</span>
0634 <span class="keyword">return</span>
0635 
0636 <span class="comment">%% Return minimum and maximum values</span>
0637 <a name="_sub9" href="#_subfunctions" class="code">function lims = min_max(A)</a>
0638 M = isfinite(A);
0639 lims = double([min(A(M)) max(A(M))]);
0640 <span class="keyword">if</span> isempty(lims)
0641     lims = [0 1];
0642 <span class="keyword">elseif</span> lims(1) == lims(2)
0643     lims(2) = lims(1) + 1;
0644 <span class="keyword">end</span>
0645 <span class="keyword">return</span></pre></div>
<hr><address>Generated on Thu 21-Mar-2013 09:32:01 by <strong><a href="http://www.artefact.tk/software/matlab/m2html/" target="_parent">m2html</a></strong> &copy; 2005</address>
</body>
</html>